package com.ctshk.rpc.scenic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.scenic.dto.ApplyUserInfoDTO;
import com.ctshk.rpc.scenic.dto.TicketLuckDrawApplyUserInfoDTO;
import com.ctshk.rpc.scenic.dto.TicketTypeLuckDrawNumDTO;
import com.ctshk.rpc.scenic.entity.TicketLuckDrawApplyUserInfo;
import com.ctshk.rpc.scenic.entity.TicketTypeLuckDraw;
import com.ctshk.rpc.scenic.entity.TicketTypeLuckDrawUser;
import com.ctshk.rpc.scenic.mapper.TicketLuckDrawApplyUserInfoMapper;
import com.ctshk.rpc.scenic.mapper.TicketTypeLuckDrawMapper;
import com.ctshk.rpc.scenic.mapper.TicketTypeLuckDrawUserMapper;
import com.ctshk.rpc.scenic.req.ApplyUserInfoReq;
import com.ctshk.rpc.scenic.req.RegistrationExportReq;
import com.ctshk.rpc.scenic.req.TicketLuckDrawApplyUserInfoReq;
import com.ctshk.rpc.scenic.req.TicketTypeLuckDrawReq;
import com.ctshk.rpc.scenic.service.ITicketLuckDrawApplyUserInfoService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 门票抽奖用户报名信息表 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-02-18
 */
@DubboService
public class TicketLuckDrawApplyUserInfoServiceImpl extends ServiceImpl<TicketLuckDrawApplyUserInfoMapper, TicketLuckDrawApplyUserInfo> implements ITicketLuckDrawApplyUserInfoService {

    @Autowired
    TicketTypeLuckDrawMapper ticketTypeLuckDrawMapper;

    @Autowired
    TicketTypeLuckDrawUserMapper typeLuckDrawUserMapper;

    /**
     * 查询报名名单
     * 根据查询编号，电话，是否同意降级，上架状态查询出：
     * 查询编号，申请人信息（姓名，电话，同意，选择场次），门票数 和报名日期
     *
     * @param req
     * @return
     */
    @Override
    public Result<PageResponse<ApplyUserInfoDTO>> FindApplyUser(ApplyUserInfoReq req) {
        if (StringUtils.isNotBlank(req.getEndTime())) {
            req.setEndTime(req.getEndTime() + " 23:59:59");
        }
        IPage<ApplyUserInfoDTO> page = new Page<>(req.getPageNo(), req.getPageSize());
        page = typeLuckDrawUserMapper.FindApplyUser(req, page);
        PageResponse<ApplyUserInfoDTO> result = new PageResponse<>(page.getRecords(), page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(), page.getCurrent(), page.getSize());

        return Result.success(result);
    }

    /**
     * 根据查询编号查询报名名单详情
     *
     * @param queryNumber
     * @return
     */
    @Override
    public TicketLuckDrawApplyUserInfoDTO userDetailByNumber(String queryNumber) {

        QueryWrapper<TicketLuckDrawApplyUserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("query_number", queryNumber);
        TicketLuckDrawApplyUserInfo drawUser = baseMapper.selectOne(queryWrapper);
        TicketLuckDrawApplyUserInfoDTO userInfoDTO = EntityUtil.convertBean(drawUser, TicketLuckDrawApplyUserInfoDTO.class);

        // 查询关联表
        List<TicketTypeLuckDrawUser> drawUserList = typeLuckDrawUserMapper.selectList(
                new QueryWrapper<TicketTypeLuckDrawUser>().lambda().eq(TicketTypeLuckDrawUser::getUserInfoId, drawUser.getId()));
        Map<Long, TicketTypeLuckDrawUser> map = drawUserList.stream().collect(Collectors.toMap(TicketTypeLuckDrawUser::getTicketTypeId, Function.identity()));

        // 查询场次信息表
        List<TicketTypeLuckDraw> ticketTypeLuckDrawList = ticketTypeLuckDrawMapper.selectList(
                new QueryWrapper<TicketTypeLuckDraw>().lambda().in(!map.keySet().isEmpty(), TicketTypeLuckDraw::getId, map.keySet()));
        List<TicketTypeLuckDrawNumDTO> tickets = EntityUtil.copyList(ticketTypeLuckDrawList, TicketTypeLuckDrawNumDTO.class);
        Map<Long, TicketTypeLuckDraw> typeLuckDrawMap = ticketTypeLuckDrawList.stream().collect(Collectors.toMap(TicketTypeLuckDraw::getId, Function.identity()));

        // 设置数量
        tickets.forEach(ticket -> {
            ticket.setNumber(map.get(ticket.getId()).getNumber());
            ticket.setWinning(map.get(ticket.getId()).getWinning());
            ticket.setCompetitionDate(typeLuckDrawMap.get(ticket.getId()).getCompetitionDate().toLocalDate().toString());
        });
        userInfoDTO.setTickets(tickets);
        return userInfoDTO;
    }


    /**
     * 修改申请人资料
     *
     * @param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result editUserInfo(TicketLuckDrawApplyUserInfoReq ticketUserInfoReq) {

        TicketLuckDrawApplyUserInfo ticketLuckDrawApplyUserInfo = EntityUtil.convertBean(ticketUserInfoReq, TicketLuckDrawApplyUserInfo.class);
        baseMapper.updateById(ticketLuckDrawApplyUserInfo);

        // 删除中间表数据
        List<TicketTypeLuckDrawUser> drawUserList = typeLuckDrawUserMapper.selectList(
                new QueryWrapper<TicketTypeLuckDrawUser>().lambda().eq(TicketTypeLuckDrawUser::getUserInfoId, ticketLuckDrawApplyUserInfo.getId()));
        List<Long> drawUserIdList = drawUserList.stream().map(TicketTypeLuckDrawUser::getId).collect(Collectors.toList());
        typeLuckDrawUserMapper.deleteBatchIds(drawUserIdList);

        for (TicketTypeLuckDrawReq ticketTypeLuckDrawReq : ticketUserInfoReq.getTickets()) {
            //中间表
            TicketTypeLuckDrawUser drawUser = new TicketTypeLuckDrawUser();
            drawUser.setNumber(ticketTypeLuckDrawReq.getNumber());
            drawUser.setTicketTypeId(ticketTypeLuckDrawReq.getId());
            drawUser.setUserInfoId(ticketLuckDrawApplyUserInfo.getId());
            drawUser.setWinning(0);
            typeLuckDrawUserMapper.insert(drawUser);
        }
        return Result.success();
    }

    /**
     * @param queryNumber
     */
    @Override
    public TicketTypeLuckDrawNumDTO selectTicketByQueryNumber(String queryNumber) {

        return baseMapper.selectTicketByQueryNumber(queryNumber);
    }

    /**
     * 抽签
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result draw(Long loginId) {
        //1.获取所有报名信息
        ApplyUserInfoReq req = new ApplyUserInfoReq();
        req.setPageNo(1);
        req.setPageSize(100000000);
        //未抽中的
        req.setStatus(0);
        IPage<ApplyUserInfoDTO> page = new Page<>(req.getPageNo(), req.getPageSize());
        page = typeLuckDrawUserMapper.FindApplyUser(req, page);
        List<ApplyUserInfoDTO> applyUsers = typeLuckDrawUserMapper.FindApplyUser(req, page).getRecords();
        if (applyUsers.size() < 1) {
            //TODO 提示暂无报名信息
            return Result.success();
        }
        //2.进行遍历匹配
        applyUsers.forEach(user -> {
            //3.是否同意降级,是:A-E级遍历匹配,否:按报名时选择的级匹配
            if (0 == user.getAgree()) {
                //不同意,获取指定的场次,按报名时选择的票价级别匹配
                LambdaQueryWrapper<TicketTypeLuckDraw> wrapper = new QueryWrapper<TicketTypeLuckDraw>().lambda();
                wrapper.eq(TicketTypeLuckDraw::getSessionCode, user.getSessionCode())
                        .eq(TicketTypeLuckDraw::getFareBasis, user.getFareBasis())
                        .ge(TicketTypeLuckDraw::getNumber, user.getNumber());
                TicketTypeLuckDraw ticketTypeLuckDraw = ticketTypeLuckDrawMapper.selectOne(wrapper);
                if (ticketTypeLuckDraw == null) {
                    //为空就跳过该场次,继续后面的匹配
                    return;
                }
                //场次余票数量减去申请数量,并更新
                ticketTypeLuckDraw.setNumber(ticketTypeLuckDraw.getNumber() - user.getNumber());
                ticketTypeLuckDraw.setGmtModified(LocalDateTime.now());
                ticketTypeLuckDraw.setModifiedId(loginId);
                ticketTypeLuckDrawMapper.updateById(ticketTypeLuckDraw);
                //当前用户更新为已抽中状态
                TicketTypeLuckDrawUser ticketTypeLuckDrawUser = new TicketTypeLuckDrawUser();
                ticketTypeLuckDrawUser.setTicketTypeId(user.getTicketTypeLuckDrawUserId());
                ticketTypeLuckDrawUser.setWinning(1);
                typeLuckDrawUserMapper.updateById(ticketTypeLuckDrawUser);
            } else {
                //同意,A-E级的场次
                LambdaQueryWrapper<TicketTypeLuckDraw> wrapper = new QueryWrapper<TicketTypeLuckDraw>().lambda();
                wrapper.eq(TicketTypeLuckDraw::getSessionCode, user.getSessionCode()).orderByAsc(TicketTypeLuckDraw::getFareBasis);
                List<TicketTypeLuckDraw> ticketTypeLuckDraws = ticketTypeLuckDrawMapper.selectList(wrapper);
                //A,B,C,D,E 从小到大排序
                // 获取当前用户申请的级别位置,防止往上越级抽签
                Integer index = null;
                for (int i = 0; i < ticketTypeLuckDraws.size(); i++) {
                    if (user.getFareBasis().equalsIgnoreCase(ticketTypeLuckDraws.get(i).getFareBasis())) {
                        index = i;
                        break;
                    }
                }
                if (index == null) {
                    return;
                }
                //获取可降级的场次
                List<TicketTypeLuckDraw> demotionSessionsList = ticketTypeLuckDraws.subList(index, ticketTypeLuckDraws.size() - 1);
                demotionSessionsList.stream().anyMatch(ticketTypeLuckDraw -> {
                    if (user.getNumber() <= ticketTypeLuckDraw.getNumber()) {
                        //场次余票数量减去申请数量,并更新
                        ticketTypeLuckDraw.setNumber(ticketTypeLuckDraw.getNumber() - user.getNumber());
                        ticketTypeLuckDraw.setGmtModified(LocalDateTime.now());
                        ticketTypeLuckDraw.setModifiedId(loginId);
                        ticketTypeLuckDrawMapper.updateById(ticketTypeLuckDraw);
                        //当前用户更新为已抽中状态
                        TicketTypeLuckDrawUser ticketTypeLuckDrawUser = new TicketTypeLuckDrawUser();
                        ticketTypeLuckDrawUser.setTicketTypeId(user.getTicketTypeLuckDrawUserId());
                        ticketTypeLuckDrawUser.setWinning(1);
                        typeLuckDrawUserMapper.updateById(ticketTypeLuckDrawUser);
                        //终止匹配
                        return true;
                    }
                    //继续降级匹配
                    return false;
                });
            }
        });
        return Result.success();
    }

    @Override
    public List<ApplyUserInfoDTO> registrationListExport(RegistrationExportReq req) {
        return typeLuckDrawUserMapper.queryAllApplyUser(req);
    }
}
